#include "uart.c"
#include <REGX52.H>
#define STATUS_INPUT_PASSWORD 0
#define STATUS_RESET_PASSWORD 1
#define STATUS_OPENING 2
// 0:输入密码  1：重设密码  2：输入正确开门
unsigned char status = STATUS_INPUT_PASSWORD;

#define PRESSED_NONE 0
#define PRESSED_BTN_1 1
#define PRESSED_BTN_2 2
#define PRESSED_BTN_3 3
#define PRESSED_BTN_4 4
#define PRESSED_BTN_MODE 5
#define PRESSED_BTN_CONFIRM 6
#define PRESSED_BTN_CANCEL 7

// ctrl+alt+ 左或者右
sbit LED_R = P0 ^ 6;
sbit LED_G = P0 ^ 5;
sbit LED_P = P0 ^ 4;

unsigned char safe_password[] = {0, 0, 0, 0};
unsigned char input_password[] = {0, 0, 0, 0};

/**
 * 灯：
 * 密码指示灯 1,2,3,4
 * 操作状态灯 5（红）,6（绿）
 *
 * 按键：
 * 密码输入按键 1,2,3,4
 * 状态切换按键 5
 * 确认按键 6
 * 返回按键 7
 *
 * 状态：
 * 1. 密码输入状态，输入密码按键，
 * 按键1,2,3,4 对应密码指示灯1,2,3,4，
 * 按键按下后对应密码指示灯亮
 * 按照输入的顺序，点亮对应的灯。
 * 按下返回按键7，取消之前的输入
 * 按下确认6，需要确保输入1234灯全部被点亮，代表密码输入正确
 * 密码输入正确后，绿灯亮。
 * 输入返回后，恢复到密码输入状态。
 *
 * 2. 密码设置状态，按下状态切换按键5，切换密码设置状态和密码输入状态
 * 密码设置状态，输入新密码，覆盖之前的密码。密码输入状态下，红色指示灯5亮起
 * 同样点亮1,2,3,4 密码后，输入确认，保存新密码，进入到密码输入状态（红色指示灯灭）
 *
 *
 * 重设密码功能：
 * 输入4个按键，不能重复，如果重复，闪灯警告
 *
 * 输入密码功能：
 * 输入4个按键，不能重复，如果重复，闪灯警告
 * 输入密码错误，闪灯警告
 * 输入正确，亮绿灯。
 * 按键关闭，相当于关闭保险箱
 */

void delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for (i = 0; i < ms; i++)
    {
        for (j = 0; j < 123; j++)
            ;
    }
}

unsigned char obtain_key_press_number()
{
    unsigned char pressed;
    unsigned char i;
    unsigned char temp;
    // 注意运算优先级
    if ((P2 & 0x7F) != 0x7F)
    {
        // x111 1110   => 1
        // x111 0111   => 4
        // x111 1110 & 0x01 == 0  末尾一定是0   == 1末尾一定是1
        temp = P2;
        for (i = 0; i < 7; i++)
        {
            if ((temp & 0x01) == 0)
            {
                pressed = i + 1;
                break;
            }
            else
            {
                temp >>= 1;
            }
        }
        // 按键被按下
        while ((P2 & 0x7F) != 0x7F)
        {
        }
        return pressed;
    }
    return PRESSED_NONE;
}

/**
 * 返回1：输入成功
 * 返回0：输入失败
 */
bit input_success(unsigned char num)
{
    unsigned char i;
    for (i = 0; i < 4; i++)
    {
        if (input_password[i] == 0)
        {
            input_password[i] = num;
            return 1;
        }
        else if (input_password[i] == num)
        {
            return 0;
        }
    }
    return 0;
}

void show_error_light()
{
    unsigned char i;
    for (i = 0; i < 3; i++)
    {
        LED_R = 0;
        delay_ms(200);
        LED_R = 1;
        delay_ms(200);
    }
}

void show_success_light()
{
    unsigned char i;
    for (i = 0; i < 3; i++)
    {
        LED_R = 0;
        LED_G = 0;
        delay_ms(200);
        LED_R = 1;
        LED_G = 1;
        delay_ms(200);
    }
}

/**
 * num = 1,2,3,4
 * 1~P0_0  =0
 * 2~P0_1
 */
void show_input_light(unsigned char num)
{
    unsigned char temp = 0x01 << (num - 1);
    P0 &= ~temp;
}

void clear_input()
{
    // 清空数组
    // 点亮的灯1,2,3,4
    unsigned char i;
    for (i = 0; i < 4; i++)
    {
        input_password[i] = 0;
    }
    P0 |= 0x0F;
}

bit compare_password_success()
{
    unsigned char i;
    for (i = 0; i < 4; i++)
    {
        if (safe_password[i] != input_password[i])
        {
            return 0;
        }
    }
    return 1;
}

bit set_password_success()
{
    unsigned char i;
    // 检查input是不是完整
    for (i = 0; i < 4; i++)
    {
        if (input_password[i] == 0)
        {
            return 0;
        }
    }

    for (i = 0; i < 4; i++)
    {
        safe_password[i] = input_password[i];
    }
    return 1;
}

void process_input_password()
{
    unsigned char pressed;
    while (status == STATUS_INPUT_PASSWORD)
    {
        pressed = obtain_key_press_number();

        switch (pressed)
        {
        case PRESSED_BTN_1:
        case PRESSED_BTN_2:
        case PRESSED_BTN_3:
        case PRESSED_BTN_4:
            if (input_success(pressed))
            {
                show_input_light(pressed);
            }
            else
            {
                show_error_light();
            }
            break;
        case PRESSED_BTN_MODE:
            // 切换模式
            // 清理已经进行的按键
            status = STATUS_RESET_PASSWORD;
            clear_input();
            LED_P = 0;
            break;
        case PRESSED_BTN_CONFIRM:
            // 检查是否输入4位密码
            // 密码比较，正确的话，进入开门状态
            // 错误：清空输入，等待重新输入
            if (compare_password_success())
            {
                // 点亮绿灯，切换状态
                LED_G = 0;
                status = STATUS_OPENING;
            }
            else
            {
                show_error_light();
            }
            break;
        case PRESSED_BTN_CANCEL:
            // 清空输入
            clear_input();
            break;
        default:
            break;
        }
    }
}

void process_reset_password()
{
    unsigned char pressed;
    while (status == STATUS_RESET_PASSWORD)
    {
        pressed = obtain_key_press_number();

        switch (pressed)
        {
        case PRESSED_BTN_1:
        case PRESSED_BTN_2:
        case PRESSED_BTN_3:
        case PRESSED_BTN_4:
            if (input_success(pressed))
            {
                show_input_light(pressed);
            }
            else
            {
                show_error_light();
            }
            break;
        case PRESSED_BTN_MODE:
            // 切换模式
            // 清理已经进行的按键
            status = STATUS_INPUT_PASSWORD;
            clear_input();
            LED_P = 1;
            break;
        case PRESSED_BTN_CONFIRM:
            // 检查是否输入4位密码
            // 将密码设置到safe password
            if (set_password_success())
            {
                // 红绿灯一起闪，切换状态
                show_success_light();
                clear_input();
            }
            else
            {
                show_error_light();
            }
            break;
        case PRESSED_BTN_CANCEL:
            // 清空输入
            clear_input();
            break;
        default:
            break;
        }
    }
}

void process_opening()
{
    unsigned char pressed;
    while (status == STATUS_OPENING)
    {
        pressed = obtain_key_press_number();

        switch (pressed)
        {
        case PRESSED_BTN_1:
        case PRESSED_BTN_2:
        case PRESSED_BTN_3:
        case PRESSED_BTN_4:
        case PRESSED_BTN_MODE:
            break;
        case PRESSED_BTN_CONFIRM:
        case PRESSED_BTN_CANCEL:
            LED_G = 1;
            status = STATUS_INPUT_PASSWORD;
            clear_input();
            break;
        default:
            break;
        }
    }
}

void main()
{
    uart_init();
    delay_ms(100);

    while (1)
    {
        switch (status)
        {
        case STATUS_INPUT_PASSWORD:
            process_input_password();
            break;
        case STATUS_RESET_PASSWORD:
            process_reset_password();
            break;
        case STATUS_OPENING:
            process_opening();
            break;
        default:
            break;
        }
    }
}
